package code.generation;

import code.parser.Clazz;
import code.parser.Method;
import code.parser.Method.Param;

public class MethodSerializeJsonJava implements MethodSerialize {


	@Override
	public String call(Method method) {
		StringBuilder sb = new StringBuilder();
		if (!method.isVirtual) {
			sb.append("{\n");
			sb.append(TAB_CHAR2);
			sb.append("try {\n");
			sb.append(TAB_CHAR3);
			sb.append("JSONObject jo = new JSONObject();\n");
			sb.append(TAB_CHAR3);
			sb.append(String.format("jo.put(\"%s\",\"%s\");\n", METHOD_NAME,
					method.name));
			for (int i = 0; i < method.params.size(); i++) {
				final Param param = method.params.get(i);
				String value = param.name;
				String type = param.type;
				
				type = converCParmType2JavaType(type);
				System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXX:"+type);
				
				if (isNumber(type)) {
					value = param.name;
				} else if("String".equals(type)){
					value = param.name;
				} else if (type.contains("[]")) {
					value = String.format(
							"new JSONArray(new Gson().toJson(%s))", param.name);
				} else {
					value = String
							.format("new JSONObject(new Gson().toJson(%s))",
									param.name);
				}
				sb.append(TAB_CHAR3);
				sb.append(String.format("jo.put(\"%s\", %s);\n", param.name,
						value));
			}
			sb.append(TAB_CHAR3);
			sb.append("JsonRemoteMethodCall.callJsonMethod(jo.toString());\n");
			sb.append(TAB_CHAR2);
			sb.append("} catch (Exception e) {\n");
			sb.append(TAB_CHAR3);
			sb.append("e.printStackTrace();\n");
			sb.append(TAB_CHAR2);
			sb.append("}\n");

			if ("void".equals(method.returnType)) {
				sb.append(TAB_CHAR2);
				sb.append("return ;");
			} else if ("int".equals(method.returnType)
					|| "long".equals(method.returnType)
					|| "short".equals(method.returnType)
					|| "byte".equals(method.returnType)) {
				sb.append(TAB_CHAR2);
				sb.append("return 0;\n");
			} else {
				sb.append(TAB_CHAR2);
				sb.append("return null;\n");
			}
			sb.append(TAB_CHAR);
			sb.append("}\n");
		} else {
			sb.append(";\n");
		}
		return sb.toString();
	}

	public String converCParmType2JavaType(String type) {
		type = type.replace("&", REF);
		type = type.replace("*", ARRAY);
		type = type.replace("MsString", CSTRING);
		return type;
	}

	public boolean isNumber(String type) {
		return "int".equals(type) || "byte".equals(type)
				|| "char".equals(type)
				|| "long".equals(type)
				|| "boolean".equals(type)
				|| "bool".equals(type)
				|| "short".equals(type);
	}

	@Override
	public String callback(Method method) {
		StringBuilder sb = new StringBuilder();
		sb.append(TAB_CHAR3);
		sb.append(String.format("if(methodName.equals(\"%s\")){",method.name));
		sb.append(LINE_CHAR);
		if (method.params != null) {
			for (int l = 0; l < method.params.size(); l++) {
				Param parm = method.params.get(l);
//				System.out.println(parm.type);
				String paramType = parm.type.replace("&", REF);
				paramType = paramType.replace("*", ARRAY);
				paramType = paramType.replace("MsString", CSTRING);
				parm.type = paramType;
//				System.err.println(parm.type);
			}
			
			for (int i = 0; i < method.params.size(); i++) {
				final Param param = method.params.get(i);
				String value = param.name;
				if ("int".equals(param.type) || "byte".equals(param.type)
						|| "char".equals(param.type)
						|| "long".equals(param.type)
						|| "boolean".equals(param.type)
						|| "bool".equals(param.type)
						|| "short".equals(param.type)) {
					value = String.format("(Integer)jo.get(\"%s\")", param.name);
				}
				else if("String".equals(param.type)){
					value = String.format("jo.get(\"%s\").toString()", param.name);
				}
				else if("String".equals(param.type)){
					value = String.format("jo.get(\"%s\").toString()", param.name);
				}
				else if (param.type.contains("[]")) {
					value = String.format(
							"new Gson().fromJson(jo.get(\"%s\").toString(), %s.class)",
							param.name, param.type);
				} else {
					value = String.format(
							"new Gson().fromJson(jo.get(\"%s\").toString(), %s.class)",
							param.name, param.type);
				}
				sb.append(TAB_CHAR4);
				sb.append(String.format("%s %s = %s;\n", param.type,
						param.name, value));
				sb.append(LINE_CHAR);

			}
			sb.append(TAB_CHAR4);
			sb.append(method.name);
			sb.append("(");
			for (int i = 0; i < method.params.size(); i++) {
				if (i != 0) {
					sb.append(",");
				}
				final Param param = method.params.get(i);
				sb.append(param.name);
			}
			sb.append(");");
			sb.append(LINE_CHAR);
			
			//return 
			sb.append(TAB_CHAR);
//			if ("void".equals(method.returnType)) {
//				sb.append(TAB_CHAR);
//				sb.append("return ;");
//				sb.append(LINE_CHAR);
//			} else if ("int".equals(method.returnType)
//					|| "long".equals(method.returnType)
//					|| "short".equals(method.returnType)
//					|| "byte".equals(method.returnType)) {
				sb.append(TAB_CHAR3);
				sb.append("return 0;");
				sb.append(LINE_CHAR);
//			} else {
//				sb.append(TAB_CHAR);
//				sb.append("return null;");
//				sb.append(LINE_CHAR);
//			}
			sb.append(TAB_CHAR3);
			sb.append("}\n");
			sb.append(LINE_CHAR);
		}
		return sb.toString();
	}

	@Override
	public String include(Clazz clazz) {
		StringBuilder sb = new StringBuilder();
		sb.append("import org.json.*;\n");
		sb.append("import com.google.gson.Gson;\n");
		sb.append("import com.post.rpc.json.*;\n");
//		sb.append("import code.generation.*;\n");
		sb.append("\n");
		sb.append("\n");
		return sb.toString();
	}

	@Override
	public String sign(Method method) {
		StringBuilder sb = new StringBuilder();
		sb.append(TAB_CHAR);
		sb.append(method.access);
		sb.append(" ");
		sb.append(method.isVirtual ? VIRTUAL : "");
		sb.append(" ");
		sb.append(method.returnType);
		sb.append(" ");
		sb.append(method.name);
		sb.append("(");
		// gen params
		if (method.params != null) {
			for (int l = 0; l < method.params.size(); l++) {
				if (l != 0) {
					sb.append(",");
				}
				Param parm = method.params.get(l);
				sb.append(parm.isConst ? CONST : POINT);
				sb.append(" ");
				String paramType = parm.type.replace("&", REF);
				paramType = paramType.replace("*", ARRAY);
				paramType = paramType.replace("MsString", CSTRING);
				sb.append(paramType);
				sb.append(" ");
				sb.append(parm.name);

			}
		}
		sb.append(")");
		return sb.toString();
	}

	@Override
	public String callbackSign() {
		StringBuilder sb = new StringBuilder();
		sb.append(TAB_CHAR);
		sb.append("public int callback(String source){");
		sb.append(LINE_CHAR);
		sb.append(TAB_CHAR);
		
		sb.append(TAB_CHAR);
		sb.append("try {\n");
		sb.append(TAB_CHAR3);
		sb.append("JSONObject jo = new JSONObject(source);\n");
		sb.append(TAB_CHAR3);
		sb.append(String.format("String methodName = jo.getString(\"%s\");\n",MethodSerialize.METHOD_NAME));
		
		sb.append("%s");
		
		sb.append(TAB_CHAR2);
		sb.append("} catch (Exception e) {\n");
		sb.append(TAB_CHAR3);
		sb.append("e.printStackTrace();\n");
		sb.append(TAB_CHAR2);
		sb.append("}\n");
		
		sb.append(TAB_CHAR2);
		sb.append("return 0;");
		sb.append(LINE_CHAR);
		
		sb.append(LINE_CHAR);
		sb.append(TAB_CHAR);
		sb.append("}");
		sb.append(LINE_CHAR);
		return sb.toString();
	}
}
